﻿\subsection{Функция копирования блоков памяти}
\label{loop_memcpy}

Настоящие функции копирования памяти могут копировать по 4 или 8 байт на каждой итерации, использовать \ac{SIMD},
векторизацию, итд.

Но ради простоты, этот пример настолько прост, насколько это возможно.

\lstinputlisting[style=customc]{memcpy.c}

\subsubsection{Простейшая реализация}

\lstinputlisting[caption=GCC 4.9 x64 оптимизация по размеру (-Os),style=customasmx86]{patterns/09_loops/memcpy/memcpy_GCC49_x64_Os_RU.s}

\lstinputlisting[caption=GCC 4.9 ARM64 оптимизация по размеру (-Os),style=customasmARM]{patterns/09_loops/memcpy/memcpy_GCC49_ARM64_Os_RU.s}

\lstinputlisting[caption=\OptimizingKeilVI (\ThumbMode),style=customasmARM]{patterns/09_loops/memcpy/memcpy_Keil_Thumb_O3_RU.s}

\subsubsection{ARM в режиме ARM}

Keil в режиме ARM пользуется условными суффиксами:

\lstinputlisting[caption=\OptimizingKeilVI (\ARMMode),style=customasmARM]{patterns/09_loops/memcpy/memcpy_Keil_ARM_O3_RU.s}

Вот почему здесь только одна инструкция перехода вместо двух.

\subsubsection{MIPS}

\lstinputlisting[caption=GCC 4.4.5 оптимизация по размеру (-Os) (IDA),style=customasmMIPS]{patterns/09_loops/memcpy/memcpy_MIPS_Os_IDA_RU.lst}

\myindex{MIPS!\Instructions!LBU}
\myindex{MIPS!\Instructions!SB}
Здесь две новых для нас инструкций: \INS{LBU} (\q{Load Byte Unsigned}) и \INS{SB} (\q{Store Byte}).
Так же как и в ARM, все регистры в MIPS имеют длину в 32 бита. Здесь нет частей регистров равных байту,
как в x86.

Так что когда нужно работать с байтами, приходится выделять целый 32-битный регистр для этого.

\INS{LBU} загружает байт и сбрасывает все остальные биты (\q{Unsigned}).

\myindex{MIPS!\Instructions!LB}
И напротив, инструкция \INS{LB} (\q{Load Byte}) расширяет байт до 32-битного значения учитывая знак.

\INS{SB} просто записывает байт из младших 8 бит регистра в память.

\subsubsection{Векторизация}

\Optimizing GCC может из этого примера сделать намного больше: \myref{vec_memcpy}.
